<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="jFlBE" id="jFlBE"><span data-lake-id="u87b01c7b" id="u87b01c7b">典型回答</span></h1>
  <p data-lake-id="u5ae72234" id="u5ae72234"><br></p>
  <p data-lake-id="u03707e0c" id="u03707e0c"><span data-lake-id="u94a19cab" id="u94a19cab">我们都知道，Redis的Key是可以设置过期时间的，那么，过期了一定会立即删除吗？</span></p>
  <p data-lake-id="u81e30ecf" id="u81e30ecf"><span data-lake-id="uc45d2ea6" id="uc45d2ea6">​</span><br></p>
  <p data-lake-id="u21020229" id="u21020229"><span data-lake-id="u18fe73ef" id="u18fe73ef">回答这个问题之前，我们先看下Redis是如何实现的Key的过期。</span></p>
  <p data-lake-id="udebc8633" id="udebc8633"><span data-lake-id="u550fd304" id="u550fd304">​</span><br></p>
  <p data-lake-id="u599b5496" id="u599b5496"><span data-lake-id="uf83adb30" id="uf83adb30">以下是官网中关于过期的实现的描述（</span><a href="https://redis.io/commands/expire/" target="_blank" data-lake-id="u23b6a89d" id="u23b6a89d"><span data-lake-id="uc8d63051" id="uc8d63051">https://redis.io/commands/expire/</span></a><span data-lake-id="u8ad1885e" id="u8ad1885e"> ）：</span></p>
  <p data-lake-id="u7128a598" id="u7128a598"><img src="https://cdn.nlark.com/yuque/0/2023/png/5378072/1693564662579-2c439295-24af-4cad-ae5e-c4793f68deaf.png?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_39%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u7e244abb" id="u7e244abb"><br></p>
  <p data-lake-id="uc6889abb" id="uc6889abb"><span data-lake-id="u2cab22c1" id="u2cab22c1">也就是说Redis的键有两种过期方式：一种是被动过期，另一种是主动过期。</span></p>
  <p data-lake-id="ufb0ce7c3" id="ufb0ce7c3"><span data-lake-id="u99b64226" id="u99b64226">被动过期指的是当某个客户端尝试访问一个键，发现该键已经超时，那么它会被从Redis中删除。</span></p>
  <p data-lake-id="u9fecd92f" id="u9fecd92f"><span data-lake-id="u9106e866" id="u9106e866">​</span><br></p>
  <p data-lake-id="u9cb22812" id="u9cb22812"><span data-lake-id="u0d836445" id="u0d836445">当然，仅仅依靠被动过期还不够，因为有些过期的键可能永远不会再被访问。这些键应该被及时删除，因此Redis会定期随机检查一些带有过期时间的键。所有已经过期的键都会从键空间中删除。</span></p>
  <p data-lake-id="u56f4a4c6" id="u56f4a4c6"><span data-lake-id="ufabda6f3" id="ufabda6f3">​</span><br></p>
  <p data-lake-id="u24b00309" id="u24b00309"><span data-lake-id="u276a78cb" id="u276a78cb">具体来说，Redis每秒会执行以下操作10次：</span></p>
  <ol list="u88388ff6">
   <li fid="u76483abe" data-lake-id="u2d487438" id="u2d487438"><span data-lake-id="ufde34b9e" id="ufde34b9e">从带有过期时间的键集合中随机选择20个键。</span></li>
   <li fid="u76483abe" data-lake-id="u069e9a26" id="u069e9a26"><span data-lake-id="u40ad2749" id="u40ad2749">删除所有已经过期的键。</span></li>
   <li fid="u76483abe" data-lake-id="u1c97cf4a" id="u1c97cf4a"><span data-lake-id="ue19d91a1" id="ue19d91a1">如果已经过期的键占比超过25%，则重新从步骤1开始。</span></li>
  </ol>
  <p data-lake-id="ubab8c148" id="ubab8c148"><br></p>
  <p data-lake-id="u4bd6a58a" id="u4bd6a58a"><span data-lake-id="u2c164763" id="u2c164763">直到过期Key的比例下降到 25% 或者这次任务的执行耗时超过了25毫秒，才会退出循环</span></p>
  <p data-lake-id="ufd4a48db" id="ufd4a48db"><span data-lake-id="ub74531d9" id="ub74531d9" class="lake-fontsize-12" style="color: rgb(77, 77, 77)">​</span><br></p>
  <p data-lake-id="ubc1ad843" id="ubc1ad843"><span data-lake-id="ud071873f" id="ud071873f">所以，Redis其实是并不保证Key在过期的时候就能被立即删除的。因为一方面惰性删除中需要下次访问才会删除，即使是主动删除，也是通过轮询的方式来实现的。如果要过期的key很多的话，就会带来延迟的情况。</span></p>
  <p data-lake-id="u7cf28401" id="u7cf28401"><span data-lake-id="u5da5b228" id="u5da5b228">​</span><br></p>
  <p data-lake-id="ua63c23b4" id="ua63c23b4"><span data-lake-id="ud8528d5f" id="ud8528d5f">​</span><br></p>
  <h1 data-lake-id="bdrVb" id="bdrVb"><span data-lake-id="uafb941f2" id="uafb941f2">扩展知识</span></h1>
  <p data-lake-id="ufab32fc3" id="ufab32fc3"><br></p>
  <h2 data-lake-id="jY02j" id="jY02j"><span data-lake-id="u41ddb22e" id="u41ddb22e">主动删除 vs 被动删除</span></h2>
  <p data-lake-id="u2a412a05" id="u2a412a05"><br></p>
  <p data-lake-id="ua12d72e9" id="ua12d72e9"><span data-lake-id="u906b0e2d" id="u906b0e2d">主动删除的优点：</span></p>
  <ol list="uf6ab8784">
   <li fid="u5ec33877" data-lake-id="u3e22187f" id="u3e22187f"><strong><span data-lake-id="u7020131e" id="u7020131e">及时释放内存</span></strong><span data-lake-id="u01549703" id="u01549703">：主动删除能够及时地释放过期键占用的内存，避免内存空间被长时间占用，从而降低了内存使用率。</span></li>
   <li fid="u5ec33877" data-lake-id="ub80570e2" id="ub80570e2"><strong><span data-lake-id="uffdbabf2" id="uffdbabf2">避免写操作延迟</span></strong><span data-lake-id="u3e871a6f" id="u3e871a6f">：由于过期键被定期删除，不会导致过多的过期键在访问时触发删除操作，因此可以减少读写操作的延迟。</span></li>
  </ol>
  <p data-lake-id="ub0d6dcb0" id="ub0d6dcb0"><span data-lake-id="u81620790" id="u81620790">主动删除的缺点：</span></p>
  <ol list="ue53fd612">
   <li fid="u84eff5ac" data-lake-id="ub6e06278" id="ub6e06278"><strong><span data-lake-id="u72958f2b" id="u72958f2b">增加系统开销</span></strong><span data-lake-id="u0ea94df8" id="u0ea94df8">：定期扫描和删除操作会增加系统的开销，特别是在有大量键需要处理时，可能会导致Redis的性能下降。</span></li>
  </ol>
  <p data-lake-id="u1193a009" id="u1193a009"><br></p>
  <p data-lake-id="u2c00ae9b" id="u2c00ae9b"><span data-lake-id="ub2af8663" id="ub2af8663">被动删除的优点：</span></p>
  <ol list="ud291c8d3">
   <li fid="ue6dba9af" data-lake-id="u9fe6c78f" id="u9fe6c78f"><strong><span data-lake-id="uec4096b1" id="uec4096b1">减少系统开销</span></strong><span data-lake-id="u39131d29" id="u39131d29">：被动删除不会定期地进行扫描和删除操作，因此可以减少系统的开销，节省计算资源。</span></li>
  </ol>
  <p data-lake-id="u7d4612ab" id="u7d4612ab"><span data-lake-id="u5c1d5966" id="u5c1d5966">被动删除的缺点：</span></p>
  <ol list="u565dc076">
   <li fid="u5cf31141" data-lake-id="u0d8eaf76" id="u0d8eaf76"><strong><span data-lake-id="u1432e985" id="u1432e985">可能导致内存占用高</span></strong><span data-lake-id="u459a7f76" id="u459a7f76">：被动删除可能导致过期键长时间占用内存，直到被访问时才被删除，这可能会导致内存占用率较高。</span></li>
   <li fid="u5cf31141" data-lake-id="u85ddc67d" id="u85ddc67d"><strong><span data-lake-id="ua9b5eca3" id="ua9b5eca3">可能导致访问延迟</span></strong><span data-lake-id="u7fa8b7fd" id="u7fa8b7fd">：当大量键同时过期并在访问时触发删除操作时，可能会导致读写操作的延迟。</span></li>
  </ol>
  <p data-lake-id="u6c3da06b" id="u6c3da06b"><span data-lake-id="u7b1d3c12" id="u7b1d3c12">​</span><br></p>
  <p data-lake-id="u043657a5" id="u043657a5"><span data-lake-id="u258bdb62" id="u258bdb62">​</span><br></p>
  <p data-lake-id="ue286213c" id="ue286213c"><strong><span data-lake-id="u9b62ea0e" id="u9b62ea0e">Redis的被动删除策略</span></strong><span data-lake-id="u57d44304" id="u57d44304">，不需要额外配置。当你设置键的过期时间（TTL）时，Redis会自动处理被动删除。</span></p>
  <p data-lake-id="u923703a0" id="u923703a0"><span data-lake-id="u62bad44d" id="u62bad44d">​</span><br></p>
  <p data-lake-id="u79a19ac8" id="u79a19ac8"><span data-lake-id="u9fbcf570" id="u9fbcf570">要使用主动删除策略，需要在Redis配置文件中设置过期键检查的频率。你可以通过设置以下配置参数来调整主动删除的行为：</span></p>
  <ul list="u9ad0f5be">
   <li fid="u5cf50aad" data-lake-id="ueb3a5fda" id="ueb3a5fda"><span data-lake-id="u9eefd1cc" id="u9eefd1cc">hz</span><span data-lake-id="uffe11ed3" id="uffe11ed3">（每秒执行的定时器频率）：增加该值可以提高主动删除的频率。</span></li>
   <li fid="u5cf50aad" data-lake-id="uf5aa1971" id="uf5aa1971"><span data-lake-id="ueea64a6e" id="ueea64a6e">maxmemory</span><span data-lake-id="ue74e5cab" id="ue74e5cab">（Redis的最大内存限制）：设置合适的最大内存限制，以确保Redis在内存不足时触发主动删除。</span></li>
  </ul>
  <p data-lake-id="u9ac82b28" id="u9ac82b28"><br></p>
  <p data-lake-id="u940b1aae" id="u940b1aae"><span data-lake-id="u6d4b5bbc" id="u6d4b5bbc">例如，在Redis配置文件中可以设置：</span></p>
  <p data-lake-id="ud48cefda" id="ud48cefda"><span data-lake-id="u2593aad1" id="u2593aad1">​</span><br></p>
  <pre lang="java"><code>
maxmemory 1gb
hz 10
</code></pre>
 </body>
</html>